package org.xiaodongwei.jvm.utils;

import java.math.BigInteger;
import java.util.regex.Pattern;

public class StringUtils {

    private static final Pattern INTEGER_PATTERN = Pattern.compile("^[-+]?\\d+$");
    private static final Pattern FLOAT_PATTERN = Pattern.compile("^[-+]?\\d+\\.\\d*([eE][-+]?\\d+)?$");
    private static final Pattern HEX_PATTERN = Pattern.compile("^0[xX][0-9a-fA-F]+$");
    private static final Pattern OCTAL_PATTERN = Pattern.compile("^0[0-7]+$");
    private static final Pattern BINARY_PATTERN = Pattern.compile("^0[bB][01]+$");
    private static final Pattern SCIENTIFIC_PATTERN = Pattern.compile("^[-+]?\\d+[eE][-+]?\\d+$");
    private static final Pattern CHAR_PATTERN = Pattern.compile("^'.'$");

    public static TypeDetectionResult detectType(String value) {
        if (value == null) {
            return new TypeDetectionResult("null", null);
        }

        // 检查空字符串
        if (value.isEmpty()) {
            return new TypeDetectionResult("String", "empty string");
        }

        // 检查boolean
        if (isBoolean(value)) {
            return new TypeDetectionResult("boolean", Boolean.valueOf(value));
        }

        // 检查char (单引号包围的单个字符)
        if (isChar(value)) {
            return new TypeDetectionResult("char", value.charAt(1));
        }

        // 检查各种数字格式
        NumberDetectionResult numberResult = detectNumberType(value);
        if (numberResult != null) {
            return new TypeDetectionResult(numberResult.type, numberResult.value);
        }

        // 默认返回String类型
        return new TypeDetectionResult("String", value);
    }

    private static boolean isBoolean(String value) {
        return "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
    }

    private static boolean isChar(String value) {
        return value.length() == 3 && value.startsWith("'") && value.endsWith("'");
    }

    private static NumberDetectionResult detectNumberType(String value) {
        // 检查十六进制
        if (HEX_PATTERN.matcher(value).matches()) {
            try {
                long longValue = Long.parseLong(value.substring(2), 16);
                return determineIntegerType(longValue, "hex");
            } catch (NumberFormatException e) {
                try {
                    new BigInteger(value.substring(2), 16);
                    return new NumberDetectionResult("BigInteger", value);
                } catch (NumberFormatException e2) {
                    return null;
                }
            }
        }

        // 检查二进制
        if (BINARY_PATTERN.matcher(value).matches()) {
            try {
                long longValue = Long.parseLong(value.substring(2), 2);
                return determineIntegerType(longValue, "binary");
            } catch (NumberFormatException e) {
                try {
                    new BigInteger(value.substring(2), 2);
                    return new NumberDetectionResult("BigInteger", value);
                } catch (NumberFormatException e2) {
                    return null;
                }
            }
        }

        // 检查八进制
        if (OCTAL_PATTERN.matcher(value).matches()) {
            try {
                long longValue = Long.parseLong(value.substring(1), 8);
                return determineIntegerType(longValue, "octal");
            } catch (NumberFormatException e) {
                try {
                    new BigInteger(value.substring(1), 8);
                    return new NumberDetectionResult("BigInteger", value);
                } catch (NumberFormatException e2) {
                    return null;
                }
            }
        }

        // 检查科学计数法
        if (SCIENTIFIC_PATTERN.matcher(value).matches()) {
            try {
                double doubleValue = Double.parseDouble(value);
                return determineFloatingType(doubleValue, "scientific");
            } catch (NumberFormatException e) {
                return null;
            }
        }

        // 检查普通浮点数
        if (FLOAT_PATTERN.matcher(value).matches()) {
            try {
                double doubleValue = Double.parseDouble(value);
                return determineFloatingType(doubleValue, "decimal");
            } catch (NumberFormatException e) {
                return null;
            }
        }

        // 检查普通整数
        if (INTEGER_PATTERN.matcher(value).matches()) {
            try {
                long longValue = Long.parseLong(value);
                return determineIntegerType(longValue, "decimal");
            } catch (NumberFormatException e) {
                try {
                    new BigInteger(value);
                    return new NumberDetectionResult("BigInteger", value);
                } catch (NumberFormatException e2) {
                    return null;
                }
            }
        }

        return null;
    }

    private static NumberDetectionResult determineIntegerType(long value, String format) {
        if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
            return new NumberDetectionResult("int", (int) value);
        } else {
            return new NumberDetectionResult("long", value);
        }
    }

    private static NumberDetectionResult determineFloatingType(double value, String format) {
        float floatValue = (float) value;
        if (Float.toString(floatValue).equals(Double.toString(value))) {
            return new NumberDetectionResult("float", floatValue);
        } else {
            return new NumberDetectionResult("double", value);
        }
    }

    // 内部类用于返回检测结果
    public static class TypeDetectionResult {
        private final String type;
        private final Object value;

        public TypeDetectionResult(String type, Object value) {
            this.type = type;
            this.value = value;
        }

        public String getType() {
            return type;
        }

        public Object getValue() {
            return value;
        }

        @Override
        public String toString() {
            return "Type: " + type + ", Value: " + value;
        }
    }

    // 内部类用于数字类型检测
    private static class NumberDetectionResult {
        private final String type;
        private final Object value;

        public NumberDetectionResult(String type, Object value) {
            this.type = type;
            this.value = value;
        }
    }
}